package com.bt.framework.ext

import android.animation.Animator
import android.animation.IntEvaluator
import android.animation.ValueAnimator
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.os.SystemClock
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.core.graphics.createBitmap
import androidx.recyclerview.widget.RecyclerView
import com.bt.framework.R


/**
 *@author:hxm
 *@date: 2025/6/16 23:37
 *@version:
 *@description:View扩展
 */

/**
 * 点击事件
 * @param block 点击事件
 */
fun <T : View> T.click(block: (T) -> Unit) = setOnClickListener {
    block(it as T)
}

/**
 * 长按事件
 * @param action 长按事件
 */
fun View.longClick(action: (View) -> Boolean) {
    setOnLongClickListener { action(it) }
}

/**
 * 首次响应防抖点击时间
 * @param wait 防抖时间 默认200毫秒
 * @param block 点击事件
 */
fun View.onClick(wait: Long = 200, block: (View) -> Unit) {
    setOnClickListener { throttleClick(wait, block) }
}

fun View.onDebounceClick(wait: Long = 200, block: (View) -> Unit) {
    setOnClickListener { debounceClick(wait, block) }
}

/**
 * 获取防重复点击监听
 * <pre>
 * 首次点击响应，防抖时间内不在执行
 * </pre>
 * @param wait 防抖时间 默认200毫秒
 * @param block 点击事件
 * @return View.OnClickListener
 */
fun throttleClick(wait: Long = 200, block: (View) -> Unit): View.OnClickListener {
    return View.OnClickListener {
        val current = SystemClock.uptimeMillis()
        val lastClickTime = (it.getTag(R.id.click_time_stamp) as? Long) ?: 0
        if (current - lastClickTime > wait) {
            it.setTag(R.id.click_time_stamp, current)
            block(it)
        }
    }
}

/**
 * 获取防抖点击监听
 * <pre>
 * 响应最后一次点击，防抖时间内不再响应
 * </pre>
 * @param wait 防抖时间 默认200毫秒
 * @param block 点击事件
 * @return View.OnClickListener
 */
fun debounceClick(wait: Long = 200, block: (View) -> Unit): View.OnClickListener {
    return View.OnClickListener {
        var action = (it.getTag(R.id.click_debounce_action) as? DebounceAction)
        if (action == null) {
            action = DebounceAction(it, block)
            it.setTag(R.id.click_debounce_action, action)
        } else {
            action.block = block
        }
        it.removeCallbacks(action)
        it.postDelayed(action, wait)
    }
}

/**
 * 防抖点击事件
 * @param view  点击视图
 * @param block 点击事件
 */
class DebounceAction(val view: View, var block: (View) -> Unit) : Runnable {
    override fun run() {
        if (view.isAttachedToWindow) {
            block(view)
        }
    }
}

/**
 * 设置View的margin
 * @param left   左边距
 * @param top    上边距
 * @param right  右边距
 * @param bottom 底边距
 */
fun View.margin(
    left: Int = Int.MAX_VALUE,
    top: Int = Int.MAX_VALUE,
    right: Int = Int.MAX_VALUE,
    bottom: Int = Int.MAX_VALUE
): View {
    val params = layoutParams as ViewGroup.MarginLayoutParams
    if (left != Int.MAX_VALUE) {
        params.marginStart = left
    }
    if (top != Int.MAX_VALUE) {
        params.topMargin = top
    }
    if (right != Int.MAX_VALUE) {
        params.marginEnd = right
    }
    if (bottom != Int.MAX_VALUE) {
        params.bottomMargin = bottom
    }
    layoutParams = params
    return this
}

/**
 * 动画设置View的宽度
 * @param targetValue 目标宽度
 * @param duration 动画时长
 * @param listener 动画监听
 * @param action 动画进度监听
 */
fun View.animateWidth(
    targetValue: Int,
    duration: Long = 400,
    listener: Animator.AnimatorListener? = null,
    action: ((Float) -> Unit)? = null
) {
    post {
        ValueAnimator.ofInt(width, targetValue).apply {
            addUpdateListener {
                width(it.animatedValue as Int)
                action?.invoke(it.animatedFraction)
            }
            if (listener != null) addListener(listener)
            setDuration(duration)
            start()
        }
    }
}

/**
 * 动画设置View的高度
 * @param targetValue 目标高度
 * @param duration 动画时长
 * @param listener 动画监听
 * @param action 动画进度监听
 */
fun View.animateHeight(
    targetValue: Int,
    duration: Long = 400,
    listener: Animator.AnimatorListener? = null,
    action: ((Float) -> Unit)? = null
) {
    post {
        ValueAnimator.ofInt(height, targetValue).apply {
            addUpdateListener {
                height(it.animatedValue as Int)
                action?.invoke(it.animatedFraction)
            }
            if (listener != null) addListener(listener)
            setDuration(duration)
            start()
        }
    }
}

/**
 * 设置View的宽度
 * @param width 宽度
 */
fun View.width(width: Int): View {
    val params = layoutParams ?: ViewGroup.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.WRAP_CONTENT
    )
    params.width = width
    layoutParams = params
    return this
}

/**
 * 获取View的高度
 * @param height 高度
 */
fun View.height(height: Int): View {
    val params = layoutParams ?: ViewGroup.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.WRAP_CONTENT
    )
    params.height = height
    layoutParams = params
    return this
}

/**
 * 宽度和高度同时动画
 * @param targetWidth 宽度
 * @param targetHeight 高度
 * @param duration 动画时长
 * @param listener 动画监听
 * @param action 动画进度监听
 */
fun View.animateWidthAndHeight(
    targetWidth: Int,
    targetHeight: Int,
    duration: Long = 400,
    listener: Animator.AnimatorListener? = null,
    action: ((Float) -> Unit)? = null
) {
    post {
        val startHeight = height
        val evaluator = IntEvaluator()
        ValueAnimator.ofInt(width, targetWidth).apply {
            addUpdateListener {
                widthAndHeight(
                    it.animatedValue as Int,
                    evaluator.evaluate(it.animatedFraction, startHeight, targetHeight)
                )
                action?.invoke(it.animatedFraction)
            }
            if (listener != null) addListener(listener)
            setDuration(duration)
            start()
        }
    }
}

/**
 * 设置View的宽度和高度
 * @param targetWidth 宽度
 * @param targetHeight 高度
 */
fun View.widthAndHeight(targetWidth: Int, targetHeight: Int): View {
    val params = layoutParams ?: ViewGroup.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.WRAP_CONTENT
    )
    params.width = targetWidth
    params.height = targetHeight
    layoutParams = params
    return this
}


/**
 * 可见性
 */

/**
 * 隐藏
 */
fun View.gone() {
    visibility = View.GONE
}

/**
 * 显示
 */
fun View.visible() {
    visibility = View.VISIBLE
}

/**
 * 占位隐藏
 */
fun View.invisible() {
    visibility = View.INVISIBLE
}

/**
 * 判断是否隐藏
 **/
fun View.isGone(): Boolean {
    return visibility == View.GONE
}

/**
 * 判断是否显示
 */
fun View.isVisible(): Boolean {
    return visibility == View.VISIBLE
}

/**
 * 判断是否占位隐藏
 */
fun View.isInvisible(): Boolean {
    return visibility == View.INVISIBLE
}

/**
 * 切换可见性
 */
fun View.toggleVisible() {
    visibility = if (visibility == View.GONE) View.VISIBLE else View.GONE
}

/**
 * 限制高度
 * @param h 高度
 * @param min 最小高度
 * @param max 最大高度
 */
fun View.limitHeight(h: Int, min: Int, max: Int): View {
    val params = layoutParams ?: ViewGroup.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.WRAP_CONTENT
    )
    when {
        h < min -> params.height = min
        h > max -> params.height = max
        else -> params.height = h
    }
    layoutParams = params
    return this
}

/**
 * 限制宽度
 * @param w 宽度
 * @param min 最小宽度
 * @param max 最大宽度
 */
fun View.limitWidth(w: Int, min: Int, max: Int): View {
    val params = layoutParams ?: ViewGroup.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.WRAP_CONTENT
    )
    when {
        w < min -> params.width = min
        w > max -> params.width = max
        else -> params.width = w
    }
    layoutParams = params
    return this
}

/**
 * 设置View的margin
 * @param startMargin 左侧边距
 * @param topMargin 顶部边距
 * @param endMargin 右侧边距
 * @param bottomMargin 底部边距
 */
fun View.margin(
    startMargin: Int = Int.MAX_VALUE,
    topMargin: Int = Int.MAX_VALUE,
    endMargin: Int = Int.MAX_VALUE,
    bottomMargin: Int = Int.MAX_VALUE,
    supportRtl: Boolean = true
): View {
    val params = layoutParams as? ViewGroup.MarginLayoutParams
    if (startMargin != Int.MAX_VALUE) {
        if (supportRtl) {
            params?.marginStart = startMargin
        } else {
            params?.leftMargin = startMargin
        }
    }
    if (topMargin != Int.MAX_VALUE) {
        params?.topMargin = topMargin
    }
    if (endMargin != Int.MAX_VALUE) {
        if (supportRtl) {
            params?.marginEnd = endMargin
        } else {
            params?.rightMargin = endMargin
        }
    }
    if (bottomMargin != Int.MAX_VALUE) {
        params?.bottomMargin = bottomMargin
    }
    params?.let {
        layoutParams = it
    }
    return this
}

/**
 * 获取View的截图, 支持获取整个RecyclerView列表的长截图
 * 注意：调用该方法时，请确保View已经测量完毕，如果宽高为0，则将抛出异常
 */
fun View.toBitmap(): Bitmap {
    if (measuredWidth == 0 || measuredHeight == 0) {
        throw RuntimeException("调用该方法时，请确保View已经测量完毕，如果宽高为0，则抛出异常以提醒！")
    }
    return when (this) {
        is RecyclerView -> {
            this.scrollToPosition(0)
            this.measure(
                View.MeasureSpec.makeMeasureSpec(this.measuredWidth, View.MeasureSpec.EXACTLY),
                View.MeasureSpec.makeMeasureSpec(this.measuredHeight, View.MeasureSpec.UNSPECIFIED)
            )
            val bmp = createBitmap(this.measuredWidth, this.measuredHeight, Bitmap.Config.ARGB_8888)
            val canvas = Canvas(bmp)
            if (this.background != null) {
                this.background.setBounds(0, 0, this.width, this.measuredHeight)
                this.background.draw(canvas)
            } else {
                canvas.drawColor(Color.WHITE)
            }
            this.draw(canvas)
            //恢复高度
            this.measure(
                View.MeasureSpec.makeMeasureSpec(this.width, View.MeasureSpec.EXACTLY),
                View.MeasureSpec.makeMeasureSpec(this.height, View.MeasureSpec.AT_MOST)
            )
            bmp
        }

        else -> {
            val screenShot = createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_4444)
            val canvas = Canvas(screenShot)
            if (background != null) {
                background.setBounds(0, 0, width, measuredHeight)
                background.draw(canvas)
            } else {
                canvas.drawColor(Color.WHITE)
            }
            draw(canvas)
            screenShot
        }
    }
}

/**
 * 获取当前View的布局gravity
 */
val View.layoutGravity: Int
    get() = when (val lp = layoutParams) {
        is FrameLayout.LayoutParams -> lp.gravity
        is LinearLayout.LayoutParams -> lp.gravity
        else -> Gravity.NO_GRAVITY
    }

/**
 * 设置当前View的布局gravity
 */
fun View.layoutGravity(gravity: Int) {
    when (val lp = layoutParams) {
        is FrameLayout.LayoutParams -> lp.gravity = gravity
        is LinearLayout.LayoutParams -> lp.gravity = gravity
        else -> return
    }
    invalidate()
}

/**
 * 获取子View
 */
inline val ViewGroup.children get() = (0 until childCount).map { getChildAt(it) }